#include <iostream>
#include <string>
#include <queue>
#include <stdlib.h>  
#include <algorithm>
#include <cmath>
#include <fstream>
#include "Event.h"
using namespace std;

queue<Event> readEventFromFile(int numApplication, string filenamePrefix) {
	queue<Event> results;
	for (int i = 0; i < numApplication; i++) {
		Application app(filenamePrefix + to_string(i) + ".txt");
		Event e(app);
		results.push(e);
		cout << e.getId() << endl;
	}
	return results;
}

int main(int argc,char* argv[]) {

	int width = atoi(argv[1]);
	string powerPrefix = "..\\simulate\\app\\power";
	//string powerPrefix = "..\\app\\app\\power";
	Map map(1, width, width, 10, 1, 1,0,powerPrefix);// 8 12 16 20 //8
	int type = 0;

	int numApplication = atoi(argv[2]);
	string applicationString = "..\\simulate\\app\\app";
	//string applicationString = "..\\app\\app";
	queue<Event> events = readEventFromFile(numApplication, applicationString);

	cout << argv[1] << endl << argv[2] << endl;
	double commCost = 0;

	vector<Event> waiting;
	vector<Event> running;
	vector<Event> finished;

	Clock* clock = Clock::getClock();
	
	
	while (finished.size() != numApplication) {
		for (vector<Event>::iterator iter = waiting.begin(); (!waiting.empty())&&iter != waiting.end();) {
			if ((*iter).getNumTasks() <= map.getAvailableCores() && (*iter).startRunning(&map,type)) {
				//map.showMap();
				commCost += (*iter).communicationCost(map);
				running.push_back(*iter);
				iter = waiting.erase(iter);
			}else{
				iter++;
			}
		}

		while (!events.empty()) {
			Event app = events.front();
			if (app.arrive(clock->now())) {
				if (app.getNumTasks() < map.getAvailableCores()&& app.startRunning(&map,type)) {
					//map.showMap();
					running.push_back(app);
					commCost += app.communicationCost(map);
					events.pop();
				}
				else {
					app.wait();
					waiting.push_back(app);
					events.pop();
				}
			}
			else {
				break;
			}

		}

		for (vector<Event>::iterator iter = running.begin(); iter != running.end();) {
			(*iter).nRound(&map);
			if ((*iter).hasFinished()) {
				finished.push_back(*iter);
				iter = running.erase(iter);
			}
			else {
				iter++;
			}
		}
		//cout << clock->now() << endl;
		//cout << "task profile:";
		map.showMap();
		cout << endl;
		map.savePower(powerPrefix);
		clock->tick();
		//map.showMap();
		//cout <<"waiting:"<< waiting.size() << endl;;
		//cout <<"running:"<< running.size()<<endl;
		//cout << "finished:" << finished.size() << endl;
		//cout <<"other"<< events.size()<<endl;

	}

	int waitingTimeSum = 0;
	for (auto iter = finished.begin(); iter != finished.end(); iter++) {
		waitingTimeSum += (*iter).getStartTime() - (*iter).getArrivalTime();
	}
	cout << "running time: " << clock->now() << endl;
	cout <<"waiting time: "<< waitingTimeSum << endl;
	cout << "communication cost:" << commCost << endl;

	//ofstream myfile;
	//myfile.open("result.txt",ios::app);
	//myfile << map.getHeight()<<"*"<<map.getWidth()<<"\t"<<numApplication<<"\t"<<numTasksRange<<"\t"<<taskExecutionVolume<<"\t"<<CCR<<"\t"<<arrivalRate<<"\t"<<type<<endl;
	//myfile << "running time: " << clock->now() << endl;
	//myfile << "waiting time: " << waitingTimeSum << endl;
	//myfile << "communication cost:" << commCost << endl;
	//myfile << endl;
	//myfile.close();
	return 0;
}